using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using TestCases.CompareAssert.Core;
using TestCases.CompareAssert.Core.Comparers.Interfaces;
using TestCases.CompareAssert.Core.Factories;
using TestCases.CompareAssert.Core.Helpers;
using TestCases.CompareAssert.Core.Interfaces;
using TestCases.CompareAssert.Core.Builders;
using TestCases.CompareAssert.Matchers;

namespace TestCases.Tests.Helpers
{
    public static class TestData
    {

        public const object Null = null;
        public const string NullString = "null";
        public const string EmptyString = "";

        public const char CharValue = 'c';
        public const string CharValueString = "\'c\'";

        public const int IntegerValue1 = 111;                
        public const int IntegerValue2 = 222;
        public const int IntegerValue3 = 333;

        public const long LongValue1 = 111L;
        public const long LongValue2 = 222L;
        public const long LongValue3 = 333L;
        

        public const string Integer1String = "111";
        public const string Integer2String = "222";
        public const string Integer3String = "333";
        
        public const string StringValue1 = "StringValue1";
        public const string StringValueString = "\"" + StringValue1 + "\"";
        
        public const string StringValue2 = "StringValue2";
        public const string StringValue3 = "StringValue3";

        public static readonly StringBuilder StringBuilder1 = new StringBuilder(StringValue1);
        public static readonly StringBuilder StringBuilder2 = new StringBuilder(StringValue2);
        public static readonly StringBuilder StringBuilder3 = new StringBuilder(StringValue3);

        public static readonly object[] ObjectArray = new object[] {IntegerValue1, StringValue1, CharValue, IntegerValue2};
        public static readonly string ObjectArrayString = String.Join(", ", new[] {Integer1String, StringValueString, CharValueString, Integer2String});
        
        public static readonly Dictionary<string, object> Dictionary1 = new Dictionary<string, object>
        {
            {"Name", "Vasiliy"},
            {"YourName", "Gavno"}
        };                

        public static readonly Dictionary<string, object> Dictionary2 = new Dictionary<string, object>
        {
            {"Name", "XXX"},
            {"YourName", "Gavno"}
        };

        public static readonly Dictionary<string, object> Dictionary3 = new Dictionary<string, object>
        {
            {"MyName", "XXX"},
            {"Name", "Vasiliy"},
            {"YourName", "Gavno"}
        };
                
        public static readonly Hashtable Hashtable1 = new Hashtable
        {
            {"Name", "Vasiliy"},
            {"YourName", "Gavno"}
        };
        
        public static readonly Hashtable Hashtable2 = new Hashtable
        {
            {"Name", "XXX"},
            {"YourName", "Gavno"}
        };
        
        public static readonly Hashtable Hashtable3 = new Hashtable
        {
            {"MyName", "XXX"},
            {"Name", "Vasiliy"},
            {"YourName", "Gavno"}
        };
        
        
        public static readonly object FormatArgs = new {Name = Dictionary1["Name"], YourName = Dictionary1["YourName"]};

        public const string FormatResult1 = "My name is {Name} and your name is {YourName}";

        public const string FormatResult2 = "My name is Vasiliy and your name is Gavno";


        public static readonly string[] EmptyStringArray1 = new string[0];        
        public static readonly string[] StringArray1 = {StringValue1, StringValue2, StringValue3};
        public static readonly string[] StringArray2 = {StringValue2, StringValue3, StringValueString};
        
        public static readonly string[] MergedStringArray1 = {StringArray1[0], StringArray1[1], StringArray1[2], StringArray2[2]};
        public static readonly string[] MergedStringArray2 = {StringArray1[0], StringArray1[1], StringArray1[2], StringArray2[1], StringArray2[2]};
        
                          
        public static readonly int[] IntArray1 = new[] {1, 2, 3, 4, 5, 6};
        public static readonly int[] IntArray2 = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
        public static readonly int[] IntArray3 = new[] {1, 2, 3, 4, 5, 99};

        public static readonly long[] LongArray1 = new long[] {1, 2, 3, 4, 5, 6};
        public static readonly long[] LongArray2 = new long[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
        public static readonly long[] LongArray3 = new long[] {1, 2, 3, 4, 5, 99};

        public static readonly ArrayList ArrayList1 = new ArrayList {1, 2, 3, 4, 5, 6};
        public static readonly ArrayList ArrayList2 = new ArrayList {1, 2, 3, 4, 5, 6, 7, 8, 9};
        public static readonly ArrayList ArrayList3 = new ArrayList {1, 2, 3, 4, 5, 99};

        public static readonly string[,] TwoDimensionalArray = new string[3,4]
        {
            {"A", "B", "C", "E"},
            {"D", "E", "F", "G"},
            {"G", "H", "I", "H"}
        };        

        public static readonly TestTypes.ComparableClass Comparable = new TestTypes.ComparableClass {Value = IntegerValue1};
        public static readonly TestTypes.CircularReferencesClass CircularReference1 = new TestTypes.CircularReferencesClass();
        public static readonly TestTypes.CircularReferencesClass CircularReference2 = new TestTypes.CircularReferencesClass();
        public static readonly TestTypes.CircularReferencesClass CircularReference3 = new TestTypes.CircularReferencesClass();
                
        static TestData()
        {
            CircularReference1.ReferencesToThis = CircularReference2;
            CircularReference2.ReferencesToThis = CircularReference1;
            CircularReference3.ReferencesToThis = CircularReference3;
        }
        
        public static readonly TestTypes.EmptyClass EmptyObject = new TestTypes.EmptyClass();

        public static readonly TestTypes.PropertiesClass PropertiesObject1 = new TestTypes.PropertiesClass(IntegerValue1)
        {
            StringValue1 = StringValue1
        };
        
        public static readonly TestTypes.PropertiesClass PropertiesObject2 = new TestTypes.PropertiesClass(IntegerValue2)
        {
            StringValue1 = StringValue1
        }; 
               
        public static readonly TestTypes.PropertiesClass2 PropertiesObject3 = new TestTypes.PropertiesClass2(IntegerValue1)
        {
            StringValue1 = StringValue1,
            StringValue2 = StringValue2
        };
        
        public static readonly TestTypes.FieldsClass FieldsObject1 = new TestTypes.FieldsClass(StringValue1, StringValue1);
        public static readonly TestTypes.FieldsClass FieldsObject2 = new TestTypes.FieldsClass(StringValue2, StringValue1);
        public static readonly TestTypes.FieldsClass2 FieldsObject3 = new TestTypes.FieldsClass2(StringValue1, StringValue2, StringValue1);

        public static readonly Type Type1 = typeof(int);
        public static readonly Type Type2 = typeof(string);
        
        public const CompareStatus CompareStatus1 = CompareStatus.Equals;
        public const CompareStatus CompareStatus2 = CompareStatus.NotEquals;
        public const CompareStatus CompareStatus3 = CompareStatus.NotApplicable;

        public static readonly IResultBuilderFactory Factory1 = FullBuilderFactory.Instance;
        public static readonly IResultBuilderFactory Factory2 = SimpleBuilderFactory.Instance;
        
        public static readonly object AnnonymousObject1 = new {IntegerValue1, IntegerValue2, IntegerValue3, Integer1String};
        public static readonly object AnnonymousObject2 = new {IntegerValue1, IntegerValue2, IntegerValue3};
        public static readonly object AnnonymousObject3 = new {IntegerValue1 = Integer2String, IntegerValue2, IntegerValue3, Integer1String};
        
        public static IResultSettings ResultSettings1 = new ResultSettings(CompareStatus1, StringValue1, AnnonymousObject1);
        public static IResultSettings ResultSettings2 = new ResultSettings(CompareStatus2, StringValue2, AnnonymousObject2);
        public static IResultSettings ResultSettings3 = new ResultSettings(CompareStatus3, StringValue3, AnnonymousObject3);
        
        public static readonly IComparerObject ComparerObject1 = ComparerObject.RootObject(StringValue1, StringValue1);
        public static readonly IComparerObject ComparerObject2 = ComparerObject.RootObject(StringValue2, StringValue2);
        public static readonly IComparerObject ComparerObject3 = ComparerObject.RootObject(StringValue3, StringValue3);

        public static readonly IObjectComparer ObjectComparer1 = new TestComparer {Settings = ResultSettings1};
        public static readonly IObjectComparer ObjectComparer2 = new TestComparer {Settings = ResultSettings2};
        public static readonly IObjectComparer ObjectComparer3 = new TestComparer {Settings = ResultSettings3};
        public static readonly IList<IObjectComparer> ObjectComparers = new[] {ObjectComparer1, ObjectComparer2, ObjectComparer3};

        public static readonly CompareContext CompareContext1 = new CompareContext(Factory1, ComparerObject1, ComparerObject2);
        public static readonly CompareContext CompareContext2 = new CompareContext(Factory2, ComparerObject1, ComparerObject2);
        public static readonly CompareContext CompareContext3 = new CompareContext(Factory1, ComparerObject1, ComparerObject3);
        public static readonly CompareContext CompareContext4 = new CompareContext(Factory2, ComparerObject1, ComparerObject1);
        public static readonly CompareContext CompareContext5 = new CompareContext(Factory1, ComparerObject2, ComparerObject3);

        public static readonly CompareResult CompareResult1 = new CompareResult(ObjectComparer1, CompareStatus1, CompareContext1)
        {
            Message = StringValue1
        };

        public static readonly CompareResult CompareResult2 = new CompareResult(ObjectComparer2, CompareStatus2, CompareContext2)
        {
            Message = StringValue2
        };

        public static readonly ICompareResult CompareResult3 = new CompareResult(ObjectComparer3, CompareStatus3, CompareContext3)
        {
            Message = StringValue3
        };
        
        public static readonly CompareResult RootCompareResult = new CompareResult(ObjectComparer3, CompareStatus3, CompareContext3, CompareResult1)
        {
            Message = StringValueString
        };

        public static readonly CompareResult[] CompareResults = new[] {CompareResult1, CompareResult2, RootCompareResult};


        public static readonly IResultBuilder NewResultBuilder1 = new ResultBuilder(ObjectComparer1, CompareStatus1, CompareContext1);
        
        //public static readonly IResultBuilder 
        public static readonly IResultBuilder ResultBuilder1 = new ReadOnlyBuilder(CompareResult1);
        public static readonly IResultBuilder ResultBuilder2 = new ReadOnlyBuilder(CompareResult2);        
        public static readonly IResultBuilder ResultBuilder3 = new ReadOnlyBuilder(CompareResult3);

        public static readonly IResultBuilder RootResultBuilder = new ReadOnlyBuilder(RootCompareResult);

        public static readonly IResultBuilder[] ResultBuilders = new[] {NewResultBuilder1, ResultBuilder2, RootResultBuilder};

        public static readonly TestTypes.EqualsToClass1 EqualsToObject1 = new TestTypes.EqualsToClass1 {TestValue = 111};
        public static readonly TestTypes.EqualsToClass2 EqualsToObject2 = new TestTypes.EqualsToClass2 {TestValue = 111};
        
        public static readonly IObjectMatcher<ICompareContext> Matcher = new ObjectMatcher<ICompareContext>();

        public static readonly int[][] DoubleArray1 = new[]
        {
            new[] {1,2,3}, 
            new[] {3,2,1}
        };

        public static readonly int[,] MultiIntArray1 = new[,]
        {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        public static readonly int[,] MultiIntArray2 = new[,]
        {
            {1, 2, 3},
            {4, 99, 6},
            {7, 8, 9}
        };
        
        
        public static readonly int[,] MultiIntArray4 = new[,]
        {
            {1, 2, 3},
            {4, 5, 6},
        };

        public static readonly int[,,,] MultiIntArray5 = new[,,,]
        {
            {
                {
                    {1, 2, 3},
                    {4, 5, 6},
                    {7, 8, 9}
                },
                {
                    {1, 2, 3},
                    {5, 6, 7},
                    {9, 10, 11},
                }
            },
            {
                {
                    {1, 2, 3},
                    {4, 5, 6},
                    {7, 8, 9}
                },
                {
                    {1, 2, 3},
                    {5, 6, 7},
                    {9, 10, 11},
                }
            },            
        };

        public static readonly int[,] EmptyMultiArray = new int[,]
        {
            {},
            {}
        };

    }
}